using System;
using System.Collections.ObjectModel;
using System.Threading;

namespace Microsoft.Xna.Framework
{
	public sealed class GameComponentCollection : Collection<IGameComponent>
	{
		private EventHandler<GameComponentCollectionEventArgs> _componentAdded;
		private EventHandler<GameComponentCollectionEventArgs> _componentRemoved;

		public event EventHandler<GameComponentCollectionEventArgs> ComponentAdded
		{
			add
			{
				EventHandler<GameComponentCollectionEventArgs> eventHandler = this._componentAdded;
				EventHandler<GameComponentCollectionEventArgs> comparand;
				do
				{
					comparand = eventHandler;
					eventHandler = Interlocked.CompareExchange(ref _componentAdded, comparand + value, comparand);
				}
				while (eventHandler != comparand);
			}
			remove
			{
				EventHandler<GameComponentCollectionEventArgs> eventHandler = this._componentAdded;
				EventHandler<GameComponentCollectionEventArgs> comparand;
				do
				{
					comparand = eventHandler;
					eventHandler = Interlocked.CompareExchange(ref _componentAdded, comparand - value, comparand);
				}
				while (eventHandler != comparand);
			}
		}

		public event EventHandler<GameComponentCollectionEventArgs> ComponentRemoved
		{
			add
			{
				EventHandler<GameComponentCollectionEventArgs> eventHandler = _componentRemoved;
				EventHandler<GameComponentCollectionEventArgs> comparand;
				do
				{
					comparand = eventHandler;
					eventHandler = Interlocked.CompareExchange(ref _componentRemoved, comparand + value, comparand);
				}
				while (eventHandler != comparand);
			}
			remove
			{
				EventHandler<GameComponentCollectionEventArgs> eventHandler = _componentRemoved;
				EventHandler<GameComponentCollectionEventArgs> comparand;
				do
				{
					comparand = eventHandler;
					eventHandler = Interlocked.CompareExchange(ref _componentRemoved, comparand - value, comparand);
				}
				while (eventHandler != comparand);
			}
		}

		protected override void InsertItem(int index, IGameComponent item)
		{
			if (this.IndexOf(item) != -1)
				throw new ArgumentException(Resources.CannotAddSameComponentMultipleTimes);
			base.InsertItem(index, item);
			if (item == null)
				return;
			this.OnComponentAdded(new GameComponentCollectionEventArgs(item));
		}

		protected override void RemoveItem(int index)
		{
			IGameComponent gameComponent = this[index];
			base.RemoveItem(index);
			if (gameComponent == null)
				return;
			this.OnComponentRemoved(new GameComponentCollectionEventArgs(gameComponent));
		}

		protected override void SetItem(int index, IGameComponent item)
		{
			throw new NotSupportedException(Resources.CannotSetItemsIntoGameComponentCollection);
		}

		protected override void ClearItems()
		{
			for (int index = 0; index < this.Count; ++index)
				this.OnComponentRemoved(new GameComponentCollectionEventArgs(this[index]));
			base.ClearItems();
		}

		private void OnComponentAdded(GameComponentCollectionEventArgs eventArgs)
		{
			if (_componentAdded == null)
				return;
			_componentAdded(this, eventArgs);
		}

		private void OnComponentRemoved(GameComponentCollectionEventArgs eventArgs)
		{
			if (_componentRemoved == null)
				return;
			_componentRemoved(this, eventArgs);
		}
	}
}